home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / X11 / xpaint-2.1.1 / lineOp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-05-03  |  7.0 KB  |  264 lines

  1. /* +-------------------------------------------------------------------+ */
  2. /* | Copyright 1992, 1993, David Koblas (koblas@netcom.com)            | */
  3. /* |                                                                   | */
  4. /* | Permission to use, copy, modify, and to distribute this software  | */
  5. /* | and its documentation for any purpose is hereby granted without   | */
  6. /* | fee, provided that the above copyright notice appear in all       | */
  7. /* | copies and that both that copyright notice and this permission    | */
  8. /* | notice appear in supporting documentation.  There is no           | */
  9. /* | representations about the suitability of this software for        | */
  10. /* | any purpose.  this software is provided "as is" without express   | */
  11. /* | or implied warranty.                                              | */
  12. /* |                                                                   | */
  13. /* +-------------------------------------------------------------------+ */
  14.  
  15. #include <X11/Intrinsic.h>
  16. #include <X11/StringDefs.h>
  17. #include <math.h>
  18. #include "xpaint.h"
  19. #include "misc.h"
  20. #include "Paint.h"
  21.  
  22. typedef struct {
  23.     int        isRay;
  24.     int        type;
  25.     Boolean        didUndo, didSet, tracking;
  26.     int        rx, ry;
  27.     int        startX, startY, endX, endY;
  28.     int        drawn;
  29.     Drawable    drawable;
  30.     GC        gcx;
  31. } LocalInfo;
  32.  
  33. static void    press(Widget w, LocalInfo *l, XButtonEvent *event, OpInfo *info) 
  34. {
  35.     /*
  36.     **  Check to make sure all buttons are up, before doing this
  37.     */
  38.     if ((event->state & (Button1Mask|Button2Mask|Button3Mask|Button4Mask|Button5Mask)) != 0)
  39.         return;
  40.  
  41.     if (event->button == Button1 && ((!l->tracking && l->isRay) || !l->isRay)) {
  42.         l->rx     = info->x;
  43.         l->ry     = info->y;
  44.         l->startX = event->x;
  45.         l->startY = event->y;
  46.  
  47.         l->drawable = info->drawable;
  48.         l->drawn = False;
  49.         l->didUndo = False;
  50.         l->didSet = False;
  51.         l->tracking = True;
  52.     } else if (event->button == Button2) {
  53.         if (l->drawn)
  54.             XDrawLine(XtDisplay(w), info->drawable, l->gcx,
  55.                     l->startX, l->startY, l->endX, l->endY);
  56.         l->tracking = False;
  57.         return;
  58.     }
  59.  
  60.     if (l->tracking) {
  61.         if (l->drawn)
  62.             XDrawLine(XtDisplay(w), info->drawable, l->gcx,
  63.                     l->startX, l->startY, l->endX, l->endY);
  64.  
  65.         l->endX = event->x;
  66.         l->endY = event->y;
  67.  
  68.         XDrawLine(XtDisplay(w), info->drawable, l->gcx,
  69.                 l->startX, l->startY, l->endX, l->endY);
  70.         l->drawn = True;
  71.     }
  72. }
  73.  
  74. static void    motion(Widget w, LocalInfo *l, XMotionEvent *event, OpInfo *info) 
  75. {
  76.     if (!l->tracking)
  77.         return;
  78.  
  79.     if (l->drawn) {
  80.         XDrawLine(XtDisplay(w), info->drawable, l->gcx,
  81.                 l->startX, l->startY, l->endX, l->endY);
  82.     }
  83.  
  84.     l->type = (event->state & ShiftMask);
  85.  
  86.     if (l->type) {
  87.         int    ax = ABS(event->x - l->startX);
  88.         int    ay = ABS(event->y - l->startY);
  89.         int    dx = MIN(ax, ay);
  90.         int    v, v1 = dx - ax, v2 = dx - ay;
  91.         int    addX, addY;
  92.  
  93.         v = v1 * v1 + v2 * v2;
  94.  
  95.         if (ay * ay < v) {
  96.             addX = event->x - l->startX;
  97.             addY = 0;
  98.         } else if (ax * ax < v) {
  99.             addX = 0;
  100.             addY = event->y - l->startY;
  101.         } else {
  102.             if (ax < ay) {
  103.                 addX = event->x - l->startX;
  104.                 addY = SIGN(event->y - l->startY) * ax;
  105.             } else {
  106.                 addX = SIGN(event->x - l->startX) * ay;
  107.                 addY = event->y - l->startY;
  108.             }
  109.         }
  110.  
  111.         l->endX = l->startX + addX;
  112.         l->endY = l->startY + addY;
  113.     } else {
  114.         l->endX = event->x;
  115.         l->endY = event->y;
  116.     }
  117.  
  118.     /*
  119.     **  Really set this flag in the if statement
  120.     */
  121.     if (l->drawn = (l->startX != l->endX || l->startY != l->endY)) {
  122.         XDrawLine(XtDisplay(w), info->drawable, l->gcx,
  123.                 l->startX, l->startY, l->endX, l->endY);
  124.     }
  125. }
  126.  
  127. static void    release(Widget w, LocalInfo *l, XButtonEvent *event, OpInfo *info) 
  128. {
  129.     XRectangle    undo;
  130.     int        mask;
  131.  
  132.     if (!l->tracking)
  133.         return;
  134.  
  135.     /*
  136.     **  Check to make sure all buttons are up, before doing this
  137.     */
  138.     mask = Button1Mask|Button2Mask|Button3Mask|Button4Mask|Button5Mask;
  139.     switch (event->button) {
  140.     case Button1:    mask ^= Button1Mask; break;
  141.     case Button2:    mask ^= Button2Mask; break;
  142.     case Button3:    mask ^= Button3Mask; break;
  143.     case Button4:    mask ^= Button4Mask; break;
  144.     case Button5:    mask ^= Button5Mask; break;
  145.     }
  146.     if ((event->state & mask) != 0)
  147.         return;
  148.  
  149.     if (l->drawn && info->surface == opWindow) {
  150.         XDrawLine(XtDisplay(w), info->drawable, l->gcx,
  151.                 l->startX, l->startY, l->endX, l->endY);
  152.         l->drawn = False;
  153.     }
  154.  
  155.     if (info->surface == opWindow && info->isFat)
  156.         return;
  157.  
  158.     if (!l->didUndo && info->surface == opPixmap) {
  159.         UndoStart(w, info);
  160.         l->didUndo = True;
  161.     }
  162.  
  163.     if (l->type) {
  164.         int    ax = ABS(event->x - l->rx);
  165.         int    ay = ABS(event->y - l->ry);
  166.         int    dx = MIN(ax, ay);
  167.         int    v, v1 = dx - ax, v2 = dx - ay;
  168.         int    addX, addY;
  169.  
  170.         v = v1 * v1 + v2 * v2;
  171.  
  172.         if (ay * ay < v) {
  173.             addX = event->x - l->rx;
  174.             addY = 0;
  175.         } else if (ax * ax < v) {
  176.             addX = 0;
  177.             addY = event->y - l->ry;
  178.         } else {
  179.             if (ax < ay) {
  180.                 addX = event->x - l->rx;
  181.                 addY = SIGN(event->y - l->ry) * ax;
  182.             } else {
  183.                 addX = SIGN(event->x - l->rx) * ay;
  184.                 addY = event->y - l->ry;
  185.             }
  186.         }
  187.  
  188.         l->endX = l->rx + addX;
  189.         l->endY = l->ry + addY;
  190.     } else {
  191.         l->endX = event->x;
  192.         l->endY = event->y;
  193.     }
  194.  
  195.     XDrawLine(XtDisplay(w), info->drawable, info->first_gc,
  196.             l->rx, l->ry, l->endX, l->endY);
  197.  
  198.     if (info->surface == opPixmap) {
  199.         XYtoRECT(l->rx, l->ry, l->endX, l->endY, &undo);
  200.  
  201.         if (l->didSet) {
  202.             UndoGrow(w, l->endY, l->endY);
  203.         } else {
  204.             UndoSetRectangle(w, &undo);
  205.             l->didSet = True;
  206.         }
  207.  
  208.         PwUpdate(w, &undo, False);
  209.     }
  210. }
  211.  
  212. /*
  213. **  Those public functions
  214. */
  215. void *LineAdd(Widget w)
  216. {
  217.     LocalInfo    *l = (LocalInfo *)XtMalloc(sizeof(LocalInfo));
  218.  
  219.     l->isRay = False;
  220.     l->tracking = False;
  221.     l->gcx   = GetGCX(w);
  222.         XtVaSetValues(w, XtNcompress, True, NULL);
  223.  
  224.     OpAddEventHandler(w, opWindow, ButtonPressMask, FALSE, (OpEventProc)press, l);
  225.     OpAddEventHandler(w, opWindow, ButtonMotionMask, FALSE, (OpEventProc)motion, l);
  226.     OpAddEventHandler(w, opWindow|opPixmap, ButtonReleaseMask, FALSE, (OpEventProc)release, l);
  227.     SetCrossHairCursor(w);
  228.     return l;
  229. }
  230. void LineRemove(Widget w, LocalInfo *l)
  231. {
  232.     OpRemoveEventHandler(w, opWindow, ButtonPressMask, FALSE, (OpEventProc)press, l);
  233.     OpRemoveEventHandler(w, opWindow, ButtonMotionMask, FALSE, (OpEventProc)motion, l);
  234.     OpRemoveEventHandler(w, opWindow|opPixmap, ButtonReleaseMask, FALSE, (OpEventProc)release, l);
  235.     XtFree((XtPointer)l);
  236. }
  237. void *RayAdd(Widget w)
  238. {
  239.     LocalInfo    *l = (LocalInfo *)XtMalloc(sizeof(LocalInfo));
  240.  
  241.     l->isRay = True;
  242.     l->tracking = False;
  243.     l->gcx   = GetGCX(w);
  244.         XtVaSetValues(w, XtNcompress, True, NULL);
  245.  
  246.     OpAddEventHandler(w, opWindow, ButtonPressMask, FALSE, (OpEventProc)press, l);
  247.     OpAddEventHandler(w, opWindow, PointerMotionMask, FALSE, (OpEventProc)motion, l);
  248.     OpAddEventHandler(w, opWindow|opPixmap, ButtonReleaseMask, FALSE, (OpEventProc)release, l);
  249.     SetCrossHairCursor(w);
  250.     return l;
  251. }
  252. void RayRemove(Widget w, LocalInfo *l)
  253. {
  254.     OpRemoveEventHandler(w, opWindow, ButtonPressMask, FALSE, (OpEventProc)press, l);
  255.     OpRemoveEventHandler(w, opWindow, PointerMotionMask, FALSE, (OpEventProc)motion, l);
  256.     OpRemoveEventHandler(w, opWindow|opPixmap, ButtonReleaseMask, FALSE, (OpEventProc)release, l);
  257.  
  258.     if (l->tracking && l->drawn)
  259.         XDrawLine(XtDisplay(w), l->drawable, l->gcx,
  260.                 l->startX, l->startY, l->endX, l->endY);
  261.  
  262.     XtFree((XtPointer)l);
  263. }
  264.